﻿using AbpOne.ToolKits.Extensions;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Threading.Tasks;
using AbpOne.Domain.Shared;

namespace AbpOne.Application.Caching {
    /// <summary>
    /// 缓存扩展
    /// </summary>
    public static class AbpOneApplicationCachingExtensions {
        /// <summary>
        /// 获取或添加缓存
        ///
        /// 我们可以在DistributedCacheEntryOptions中可以配置我们的缓存过期时间，其中有一个判断条件，就是当minutes = -1的时候，不指定过期时间，那么我们的缓存就不会过期了
        /// 
        /// GetStringAsync()、SetStringAsync()是DistributedCacheExtensions的扩展方法，最终会将缓存项cacheItem转换成JSON格式进行存储
        /// </summary>
        /// <typeparam name="TCacheItem"></typeparam>
        /// <param name="cache"></param>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <param name="minutes"></param>
        /// <returns></returns>
        public static async Task<TCacheItem> GetOrAddAsync<TCacheItem>(this IDistributedCache cache, string key,
            Func<Task<TCacheItem>> factory, int minutes) {
            TCacheItem cacheItem;

            var result = await cache.GetStringAsync(key);
            if (string.IsNullOrEmpty(result)) {
                cacheItem = await factory.Invoke();

                var options = new DistributedCacheEntryOptions();
                if (minutes != CacheStrategy.NEVER) {
                    options.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(minutes);
                }

                await cache.SetStringAsync(key, cacheItem.ToJson(), options);
            }
            else {
                cacheItem = result.FromJson<TCacheItem>();
            }

            return cacheItem;
        }
    }
}